use serde::{Deserialize, Serialize};
use strum::{Display, EnumString, EnumVariantNames};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolCall {
    /// The ID of the tool call.
    pub id: String,
    /// The type of the tool. Currently, only function is supported.
    pub r#type: ToolType,
    /// The function that the model called.
    pub function: FunctionCall,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FunctionCall {
    /// The name of the function to call.
    pub name: String,
    /// The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function.
    pub arguments: String,
}

#[derive(
    Debug,
    Clone,
    Copy,
    PartialEq,
    Eq,
    Default,
    Serialize,
    Deserialize,
    EnumString,
    Display,
    EnumVariantNames,
)]
#[serde(rename_all = "snake_case")]
pub enum ToolType {
    #[default]
    Function,
}

#[derive(Debug, Clone, Serialize)]
pub struct ToolDefinition {
    /// The schema of the tool. Currently, only functions are supported.
    pub r#type: ToolType,
    pub function: FunctionInfo,
}

#[derive(Debug, Clone, Serialize)]
pub struct FunctionInfo {
    /// A description of what the function does, used by the model to choose when and how to call the function.
    pub description: String,
    /// The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64.
    pub name: String,
    /// The parameters the functions accepts, described as a JSON Schema object.
    pub parameters: serde_json::Value,
}

#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, EnumString, Display, EnumVariantNames)]
#[serde(rename_all = "snake_case")]
pub enum ToolChoice {
    None,
    #[default]
    Auto,
    // TODO: we need something like this: #[serde(tag = "type", content = "function")]
    // Function {
    //     name: String,
    // },
}